#include "stdafx.h"
#include "InputData.h"
#include <boost/tokenizer.hpp>
#include <vector>
InputData::InputData()
{
	TiXmlBase::SetCondenseWhiteSpace(true);
}
InputData::InputData(const string& filename):
_doc(filename.c_str())
{
	TiXmlBase::SetCondenseWhiteSpace(true);
}
InputData::~InputData()
{
}
bool InputData::LoadFile(const string& filename)
{
	if ( _doc.LoadFile(filename.c_str()) )
	{
		TiXmlBase::SetCondenseWhiteSpace(true);
		return true;
		}
	else
	{
        return false;
	}
}
const TiXmlElement* InputData::query(const string& name) const
{
	return _doc.FirstChildElement()
		->FirstChildElement(
		name.c_str()
		);
}
bool InputData::Text(const TiXmlElement* const pElm, string& content) const
{
	const char* obj;
	obj = 	pElm->FirstChild()->ToText()->Value();
	if ( obj )
	{
        content.assign(obj);
        return true;
	}
	else
	{
		return false;
	}
}
bool InputData::area(double& a) const
{
	return retrieve("WatershedArea", a);
}

bool InputData::TimeInterval( unsigned int& ti ) const
{
	return retrieve("TimeInterval", ti);
}
bool InputData::retrieve(const string& label, unsigned int& data) const
{
	string content;
	if (const TiXmlElement* pElm = query(label))
	{
		if ( Text(pElm,content) )
		{
			data = atoi(content.c_str());
			return true;
		}
		else
			return false;
	}
	else
		return false;
}
bool InputData::retrieve(const string& label, double& data) const
{
	string content;
	if (const TiXmlElement* pElm = query(label))
	{
		if ( Text(pElm,content) )
		{
			data = atof(content.c_str());
			return true;
		}
		else
			return false;
	}
	else
		return false;
}
bool InputData::retrieve(const string& label, doubleContainer& data) const
{
	data.clear();
	string content;
	if (const TiXmlElement* pElm = query(label))
	{
		if ( Text(pElm,content) )
		{
			data = token(content);
			return true;
		}
		else
			return false;
	}
	else
	{
		return false;
	}
}
bool InputData::retrieve(const string& label, string& data) const
{
	string content;
	if (const TiXmlElement* pElm = query(label))
	{
		if ( Text(pElm,data) )
		{
			return true;
		}
		else
			return false;
	}
	else
	{
		return false;
	}
}

bool InputData::nGeneration(unsigned int& n) const
{
	return retrieve("nGeneration", n);
}
vector<double> InputData::token(const string& input) const
{
	using namespace boost;
	using namespace std;
	typedef boost::tokenizer<boost::char_separator<char> > 
    tokenizer;
	vector<double> data;
	boost::char_separator<char> sep(", \n");  // add delimeter here
	tokenizer tok(input, sep);
	for(tokenizer::iterator beg=tok.begin(); beg!=tok.end();++beg)
   {
	   data.push_back(
		   atof( (*beg).c_str() )
		   );
   }
   return data;
   // TO DO
   // A token getter for pure string
}
bool InputData::ModelParameters(doubleContainer& mp) const
{
	return retrieve("ModelParameters", mp);
}
bool InputData::ModelConfiguration(string& con) const
{
	return retrieve("ModelConfiguration", con);
}
// genetic algorithms parameters
bool InputData::nPopulation(unsigned int& n) const
{
	return retrieve("nPopulation", n);
}
bool InputData::pCrossOver(double& p) const
{
	return retrieve("pCrossOver", p);
}
bool InputData::pMutation(double& p) const
{
	return retrieve("pMutation", p);
}
// rainfall records
bool InputData::ObservedRainfall(doubleContainer& or) const
{
	return retrieve("ObservedRainfall", or);
}
bool InputData::OptionalRainfall(doubleContainer& or) const
{
	return retrieve("OptionalRainfall", or);
}
	// runoff records
bool InputData::ObservedRunoff(doubleContainer& or) const
{
	return retrieve("ObservedRunoff", or);
}
bool InputData::OptionalRunoff(doubleContainer& or) const
{
	return retrieve("OptionalRunoff", or);
}
// objective function
bool InputData::ObjectiveFunction(string& of) const
{
	return retrieve("ObjectiveFunction", of);
}
// get Sill Length
bool InputData::SillLength(double& n) const
{
	return retrieve("SillLength", n);
}

// get Sill lower bound
bool InputData::SillLowerBound(double& lower) const
{
	return retrieve("SillMin", lower);
}
// get Sill upper bound
bool InputData::SillUpperBound(double& upper) const
{
	return retrieve("SillMax", upper);
}